package tge

import (
	"time"
	"sync"
	"runtime/debug"
)

type Session interface {
	Close()
}

// 网络连接代理接口
type Agent interface {
	WriteMsg(msg interface{}) (int, error)
	WriteWithBase64([]byte, []byte) (int, error)
	WriteBuf(msg... []byte) (int, error)
	Write(msg []byte) (int, error)
	Addr() string
	Close()
	Run()
	UserData() Session
	SetUserData(data Session)

	SetReadDeadline(t time.Time)
}

type Agenter struct {
	Parser 		ProtoParser
	Router		Route 		// 消息路由器
	conn 		Conn
	data 		Session
	w 			chan interface{}
	mu 			sync.Mutex
}

func NewAgenter(p ProtoParser, r Route, conn Conn) *Agenter {
	a := &Agenter{}
	a.Parser = p
	a.Router = r
	a.conn = conn
	return a
}

// 接收数据
func (a *Agenter) Run() {
	defer func() {
		if err := recover(); err != nil {
			logger.Println(err, string(debug.Stack()))
		}
	} ()
	for {
		buf, err := a.conn.ReadMsg()
		if nil != err {
			break
		}
		id, msg, err := a.Parser.Unmarshal(buf)
		if nil == err {
			a.Router.Route(id, &MsgPack{msg, buf}, a)
		} else {
			// logger.Println(err, buf)
		}
	}
}

func (a *Agenter) WriteMsg(msg interface{}) (int, error) {
	buff, err := a.Parser.Marshal(msg)
	if nil == err {
		a.conn.WriteMsg(buff)
	}
	return 0, err
}

func (a *Agenter) WriteBuf(msg... []byte) (int, error) {
	return a.conn.WriteMsg(msg...)
}

func (a *Agenter) Write(msg []byte) (int, error) {
	return a.conn.WriteMsg(msg)
}
	
func (a *Agenter) WriteWithBase64(buf []byte, buf64 []byte) (int, error) {
	return a.conn.WriteWithBase64(buf, buf64)
}

func (a *Agenter) Addr() string{
	if a.conn != nil {
		return a.conn.RemoteAddr().String()
	}
	return ""
}

func (a *Agenter) Close() {
	a.mu.Lock()
	if nil != a.data {
		d := a.data
		a.data = nil
		defer d.Close()
	}
	defer a.mu.Unlock()
	a.conn.Close()
}

func (a *Agenter) UserData() Session {
	a.mu.Lock()
	defer a.mu.Unlock()
	return a.data
}

func (a *Agenter) SetUserData(data Session) {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.data = data
}

func (a *Agenter) SetReadDeadline(t time.Time) {
	a.conn.SetReadDeadline(t)
}